/*
 * xmlHandler.java
 *
 * Created on 2007/11/30, 13:11
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package xsd;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 *
 * <E> you provide root element class of jaxb document, like 'xmlCommon.Root'
 * @author verifsp7
 */
public class xmlHandler<E> {
    private boolean m_updated=false;
    private Document m_doc;
    private String m_xmlFilePath;
    private String m_xsdFilePath;
    private String m_xmlOutputFilePath;
    private boolean m_validateFlag=false;
    private String m_packageName;
    private String m_namespaceURL="http://xml.netbeans.org/schema";
    private String m_schemaLocation;
    private JAXBContext m_jc;
    private E m_documentRoot;


    /** Creates a new instance of defineSelector */
    public xmlHandler(String xmlfile, String xsdPrefix) {
        m_xmlFilePath=xmlfile;
        m_packageName="xjc"+xsdPrefix.substring(0,1).toUpperCase()+
                xsdPrefix.substring(1);
        m_xsdFilePath=System.getProperty("user.dir")+"/src/xsd/"+xsdPrefix+".xsd";
        if(xmlfile!=null && ! (new File(m_xmlFilePath)).canRead()){
            System.out.println("can't read xml file: "+m_xmlFilePath);
        }else if(! (new File(m_xsdFilePath)).canRead()){
            System.out.println("can't read xmlSchema file: "+m_xsdFilePath);
        }
        m_xmlOutputFilePath=m_xmlFilePath;
        String[] d=m_xsdFilePath.split("/");
        m_schemaLocation=String.format("%s %s"
            ,m_namespaceURL,d[d.length-1]);
    }
    // Setter
    public void setM_updated(boolean f){ m_updated=f;}
    public void setM_xmlFilePath(String path){
        m_xmlFilePath=path;
        if(m_xmlOutputFilePath==null) m_xmlOutputFilePath=m_xmlFilePath;
    }
    public void setM_xmlOutputFilePath(String path){ m_xmlOutputFilePath=path;}
    @SuppressWarnings("unchecked")
    public <T> void setM_documentRoot(T root) { m_documentRoot = (E) root;}

    // Getter
    public boolean isM_updated(){ return(m_updated);}
    /**
     * Returns field parameter <b>m_xmlFilePath</b>.
     * @return XML file path to read out
     */
    public String getM_XmlFilePath() { return(m_xmlFilePath);}
    /**
     * Returns field parameter <b>m_xmlOutputFilePath</b>.
     * @return XML file path to output
     */
    public String getM_xmlOutputFilePath() { return m_xmlOutputFilePath;}
    /**
     * Returns field parameter <b>m_xsdFilePath</b>.
     * @return XML Schema file path to read out
     */
    public String getM_XsdFilePath() { return(m_xsdFilePath);}
    /**
     * Returns root object of XML to handle all methods in XML.
     * @return XML root object
     */
    public E getM_documentRoot(){ return(m_documentRoot);}
    /*
    public xmlDefineSelector.ObjectFactory getObjectFactory(){
        return(new xmlDefineSelector.ObjectFactory());
    }
     */

    //
    /**
     * Validates XML file by XML Schema file.
     * @return validating result
     */
    public boolean execValidate(){
        m_validateFlag=false;
        try {
            DocumentBuilderFactory domFactory=DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true);
            DocumentBuilder builder=domFactory.newDocumentBuilder();
            m_doc=builder.parse(new File(m_xmlFilePath));
            SchemaFactory constraintFactory=
                SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Source constraints = new StreamSource(new File(m_xsdFilePath));
            Schema schema = constraintFactory.newSchema(constraints);
            Validator va=schema.newValidator();
            va.validate(new DOMSource(m_doc));
            System.out.println("Document validates fine: "+m_xmlFilePath);
            m_validateFlag=true;
        } catch (SAXException ex) {
            System.out.println("error - validation: "+ex.getMessage());
            //ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ParserConfigurationException ex) {
            ex.printStackTrace();
        }
        return(m_validateFlag);
    }    /**
     * Reads XML file <b>m_xmlFilePath</b> to unmarshall to
     * <b>m_root</b> field parameter in this instance.
     * @return unmarshalled instance or <i>null</i> if failed
     */
    @SuppressWarnings("unchecked")
    public E unmarshaller(){
        try {
            m_jc=JAXBContext.newInstance(m_packageName);
            SchemaFactory factory=
                SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema=factory.newSchema(new File(m_xsdFilePath));
            Unmarshaller u=m_jc.createUnmarshaller();
            u.setSchema(schema);

            FileInputStream fis=new FileInputStream(m_xmlFilePath);
            m_documentRoot=(E) u.unmarshal(fis);
            fis.close();

            //m_documentRoot=(E) u.unmarshal(new InputStreamReader(fis,"EUC-JP"));
            //m_documentRoot=(E) u.unmarshal(new libUI.ucEncode(m_xmlFilePath, "UTF-8").encode());
            /*
            m_documentRoot=(E) u.unmarshal(
                    new FileInputStream(
                    new libUI.ucEncodeXml(m_xmlFilePath, "UTF-8").encodedFile()));
             */
            return(m_documentRoot);
        } catch (SAXException ex) {
            ex.printStackTrace();
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (JAXBException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return(null);
    }
    /**
     * Outputs current XML in this instance to STDOUT using marshaller.
     */
    public void marshallerToStd(){
        marshaller(System.out);
    }    /**
     * Outputs current XML in this instance to file <b>m_xmlOutputFilePatn</b>
     * using marshaller.
     */
    public void marshallerToFile(){
        if(m_xmlOutputFilePath==null || m_xmlOutputFilePath.length()==0){
            System.out.println("error - output File Path is void in marshaller()");
            return;
        }
        try {
            FileOutputStream fos=new FileOutputStream(m_xmlOutputFilePath);
            marshaller(fos);
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
        m_updated=false;
    }
    /**
     * Outputs current XML in this instance to output stream using marshaller.
     * @param osrm output stream to write on
     */
    public void marshaller(OutputStream osrm){
        String encode;
        try {
            encode = comFunc.encodingMap(comFunc.getEncodingInFile(m_xmlFilePath));
        } catch (FileNotFoundException ex) {
            //ex.printStackTrace();
            encode = comFunc.encodingMap(System.getProperty("file.encoding"));
        } catch (IOException ex) {
            ex.printStackTrace();
            encode = comFunc.encodingMap(System.getProperty("file.encoding"));
        }
        try {
            if(m_jc==null) m_jc=JAXBContext.newInstance(m_packageName);
            Marshaller m=m_jc.createMarshaller();
            SchemaFactory factory=
                SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema = factory.newSchema(new File(m_xsdFilePath));
            m.setSchema(schema);
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);
            m.setProperty(Marshaller.JAXB_ENCODING,encode);
            m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,m_schemaLocation);
            m.marshal(m_documentRoot,osrm);
        } catch (SAXException ex) {
            ex.printStackTrace();
        } catch (PropertyException ex) {
            ex.printStackTrace();
        } catch (JAXBException ex) {
            ex.printStackTrace();
        }
    }

    //***** CUSTOMIZED CODE *****

}
